package jnote;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;

public class FindReplace extends JFrame implements ActionListener {
    private final JPanel jPanel1 = new JPanel();
    private final JPanel jPanel2 = new JPanel();
    private final JButton jbClose = new JButton();
    private final JButton jbCancel = new JButton();
    private final JButton jbFind = new JButton();
    private final JButton jbStart = new JButton();
    private final JCheckBox jcbCaseSensitive = new JCheckBox();
    private final JCheckBox jcbCaseSensitive2 = new JCheckBox();
    private final JCheckBox jcbReplaceAll = new JCheckBox();
    private final JLabel jlFind = new JLabel();
    private final JLabel jlFind2 = new JLabel();
    private final JLabel jlReplace = new JLabel();
    private final JTextField jtfFind = new JTextField();
    private final JTextField jtfFind2 = new JTextField();
    private final JTextField jtfReplace = new JTextField();
    protected JTabbedPane tabFindReplace = new JTabbedPane();
    private JTextArea textArea = new JTextArea();
    
    FindReplace(JTextArea tx) {
    	textArea = tx;
        initComponents();
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        
        this.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {
            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
                Highlighter h = textArea.getHighlighter();
                h.removeAllHighlights();
            }

            @Override
            public void windowIconified(WindowEvent e) {
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
            }

            @Override
            public void windowActivated(WindowEvent e) {
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
            }
        });
    }
    
    private void initComponents() {     
        jbFind.addActionListener(this);
        jbStart.addActionListener(this);
        jbClose.addActionListener(this);
        jbCancel.addActionListener(this);
        
        jlFind.setText("Find text");
        jbFind.setText("Start");
        jcbCaseSensitive.setText("Case sensitive");
        jbClose.setText("Close");
        jcbCaseSensitive.setSelected(true);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jlFind)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jcbCaseSensitive)
                                .addGap(42, 42, 42))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                                .addComponent(jbFind)
                                .addGap(18, 18, 18)))
                        .addComponent(jbClose)
                        .addGap(0, 120, Short.MAX_VALUE))
                    .addComponent(jtfFind))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(34, 34, 34)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jlFind)
                    .addComponent(jtfFind, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(13, 13, 13)
                .addComponent(jcbCaseSensitive)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jbFind)
                    .addComponent(jbClose))
                .addContainerGap(30, Short.MAX_VALUE))
        );

        tabFindReplace.addTab("Find", jPanel1);
        jbStart.setText("Start");
        jbCancel.setText("Close");
        jlFind2.setText("Find Text");
        jlReplace.setText("Replace with");
        jcbReplaceAll.setText("Replace all");
        jcbCaseSensitive2.setText("Case sensitive");
        jcbCaseSensitive2.setSelected(true);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jlReplace)
                    .addComponent(jlFind2))
                .addGap(18, 18, 18)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jtfFind2)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jbStart)
                            .addComponent(jcbCaseSensitive2))
                        .addGap(18, 18, 18)
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jbCancel)
                            .addComponent(jcbReplaceAll))
                        .addGap(0, 91, Short.MAX_VALUE))
                    .addComponent(jtfReplace))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jlFind2)
                    .addComponent(jtfFind2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jlReplace)
                    .addComponent(jtfReplace, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jcbCaseSensitive2)
                    .addComponent(jcbReplaceAll))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jbStart)
                    .addComponent(jbCancel))
                .addGap(105, 105, 105))
        );
        
        tabFindReplace.addTab("Replace", jPanel2);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tabFindReplace)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tabFindReplace, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        pack();
    }
    
    public void find(JTextArea textArea, String toFind) {
    	Highlighter h = textArea.getHighlighter();
    	h.removeAllHighlights();
    	
    	if(!jtfFind.getText().equals("")) {
            if(textArea.getText().contains(toFind)) {
                try {
                    /*
                     * Return the position of the given word
                     * and move the caret to the end of the word.
                     */
                    int pos = textArea.getText().indexOf(toFind, 0);
                    textArea.setCaretPosition(pos + toFind.length());
                    /*
                     * Highlight the found word
                     */
                    h.addHighlight(pos, pos + toFind.length(), DefaultHighlighter.DefaultPainter);
                } catch(BadLocationException ble) {
                }
            } else {
                JOptionPane.showMessageDialog(this, "Text not found");
            }
    	} else {
            JOptionPane.showMessageDialog(this, "Nothing to search for");
        }
    }
    
    public void replaceAll(JTextArea textArea, String toFind, String toReplace) {
        if(!jtfFind2.getText().equals("") && !jtfReplace.getText().equals("")) {
            int occurrences = 0;
            do {
                int pos = textArea.getText().indexOf(toFind, 0);
                textArea.replaceRange(toReplace, pos, pos + toFind.length());
                textArea.setCaretPosition(pos + toReplace.length());
                occurrences++;
            }
            while(textArea.getText().contains(toFind));

            JOptionPane.showMessageDialog(this, occurrences + " occurrences replaced");
        } else if(!textArea.getText().contains(toFind)) {
            JOptionPane.showMessageDialog(this, "Text not found");
    	} else if(jtfFind2.getText().equals("")) {
            JOptionPane.showMessageDialog(this, "Nothing to search for");
    	} else if(jtfReplace.getText().equals("")) {
            JOptionPane.showMessageDialog(this, "Nothing to replace");
    	}        
    }
    
    private void replace(JTextArea textArea, String toFind, String toReplace) {
        if(!jtfFind2.getText().equals("") && !jtfReplace.getText().equals("")) {
            if(textArea.getText().contains(toFind)) {
            	int pos = textArea.getText().indexOf(toFind, 0);
            	textArea.replaceRange(toReplace, pos, pos + toFind.length());
            	textArea.setCaretPosition(pos + toReplace.length());
            }
    	} else if(!textArea.getText().contains(toFind))	{
            JOptionPane.showMessageDialog(this, "Text not found");
    	} else if(jtfFind2.getText().equals("")) {
            JOptionPane.showMessageDialog(this, "Nothing to search for");
    	} else if(jtfReplace.getText().equals("")) {
            JOptionPane.showMessageDialog(this, "Nothing to replace");
    	}
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == jbFind) {
            if(jcbCaseSensitive.isSelected()) {
                find(textArea, jtfFind.getText());
            } else if(!jcbCaseSensitive.isSelected()) {
                // TODO
                JOptionPane.showMessageDialog(this, "Not yet implemented");
            }
        } else if(e.getSource() == jbStart) {
            if(jcbReplaceAll.isSelected() && !jcbCaseSensitive2.isSelected()) {
                // TODO
                JOptionPane.showMessageDialog(this, "Not yet implemented");
            } else if(jcbReplaceAll.isSelected() && jcbCaseSensitive2.isSelected()) {
                replaceAll(textArea, jtfFind2.getText(), jtfReplace.getText());
            } else if(!jcbReplaceAll.isSelected() && !jcbCaseSensitive2.isSelected()) {
                // TODO
                JOptionPane.showMessageDialog(this, "Not yet implemented");
            } else if(!jcbReplaceAll.isSelected() && jcbCaseSensitive2.isSelected()) {
                replace(textArea, jtfFind2.getText(), jtfReplace.getText());
            }                
        } else if(e.getSource() == jbClose || e.getSource() == jbCancel) {
            dispose();
        }
    }
}
